Carbon instensity of Sustainable PV for Energy Transition¶

This analysis explores the carbon implications of different PV sustainability/circular economy designs in the context of achieving energy transition. These calculations build upon previous work that can be found in journals 13 and 17.

Attempt 1

In [1]:
import numpy as np
import pandas as pd
import os,sys
from pathlib import Path
import matplotlib.pyplot as plt

cwd = os.getcwd() #grabs current working directory

testfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP' / 'CarbonAnalysis')
inputfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP')
baselinesfolder = str(Path().resolve().parent.parent /'PV_ICE' / 'baselines')
supportMatfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'baselines' / 'SupportingMaterial')
carbonfolder = str(Path().resolve().parent.parent / 'PV_ICE'/ 'baselines'/ 'CarbonLayer')
altBaselinesfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'baselines' / 'Energy_CellModuleTechCompare')
energyanalysisfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP' / 'EnergyAnalysis')

if not os.path.exists(testfolder):
    os.makedirs(testfolder)
In [2]:
from platform import python_version 
print(python_version())
3.8.8
In [3]:
import PV_ICE
PV_ICE.__version__
Out[3]:
'v0.2.0+524.g195d549.dirty'
In [144]:
#https://www.learnui.design/tools/data-color-picker.html#palette
#color pallette - modify here for all graphs below
colorpalette=['#000000', #PV ICE baseline
              '#595959', '#7F7F7F', '#A6A6A6', '#D9D9D9', #BAU, 4 grays, perc, shj, topcon, irena
              #'#067872','#0aa39e','#09d0cd','#00ffff', #realistic cases (4) teals, perc, shj, topcon, irena
              '#0579C1','#C00000','#FFC000', #extreme cases (3) long life, high eff, circular
                '#6E30A0','#00B3B5','#10C483', #ambitious modules (5) high eff+ long life, 50 yr perc, recycleSi, 
               '#97CB3F','#FF7E00' #circular perovskite+life, circular perovkiste+ high eff
                ] 

colormats = ['#00bfbf','#ff7f0e','#1f77be','#2ca02c','#d62728','#9467BD','#8C564B', 'black'] #colors for material plots       

import matplotlib as mpl #import matplotlib
from cycler import cycler #import cycler
mpl.rcParams['axes.prop_cycle'] = cycler(color=colorpalette) #reset the default color palette of mpl

from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)

plt.rcParams.update({'font.size': 14})
plt.rcParams['figure.figsize'] = (8, 6)

scennames_labels = ['PV_ICE','PERC','SHJ','TOPCon','Low\nQuality',
                         'Long-Lived','High Eff','Circular',
                        'High Eff\n+ Long-life','Long-Life\n+ Recycling',
                         'Recycled-Si\n+ Long-life','Circular\n+ Long-life',
                        'Circular\n+ High Eff'
                    ]  

scennames_labels_flat = ['PV_ICE','PERC','SHJ','TOPCon','Low Quality',
                         'Long-Lived','High Eff','Circular',
                        'High Eff + Long-life','Long-Life + Recycling',
                         'Recycled-Si + Long-life','Circular + Long-life',
                        'Circular + High Eff'
                    ] 
In [5]:
MATERIALS = ['glass', 'silicon', 'silver', 'aluminium_frames', 'copper', 'encapsulant', 'backsheet']
moduleFile_m = os.path.join(baselinesfolder, 'baseline_modules_mass_US.csv')
moduleFile_e = os.path.join(baselinesfolder, 'baseline_modules_energy.csv')
In [6]:
#load in the simulation from Energy Analysis journal
sim1 = PV_ICE.Simulation.load_Simpickle(filename=r'C:\Users\hmirletz\Documents\GitHub\PV_ICE\PV_ICE\TEMP\EnergyAnalysis\sim1.pkl')

sim1.calculateCarbonFlows()

sim1.scenario['r_PERC'].dataOut_c

In [7]:
sim1.scenario['r_PERC'].dataOut_m
Out[7]:
Area Cumulative_Active_Area EOL_BadStatus EOL_Landfill0 EOL_PATHS EOL_PG Effective_Capacity_[W] Landfill_0_ProjLife MerchantTail_Area MerchantTail_[W] ... Yearly_Sum_Area_PathsBad Yearly_Sum_Area_PathsGood Yearly_Sum_Area_atEOL Yearly_Sum_Power_EOLby_Degradation Yearly_Sum_Power_EOLby_Failure Yearly_Sum_Power_EOLby_ProjectLifetime Yearly_Sum_Power_PathsBad Yearly_Sum_Power_PathsGood Yearly_Sum_Power_atEOL irradiance_stc
0 5.237421e+06 5.237421e+06 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 7.520622e+08 0.000000e+00 0.0 0.0 ... 0.000000e+00 0.000000e+00 0.000000e+00 0.0 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 1070.0
1 2.381558e+06 7.618978e+06 5.019410e-03 2.844333e-02 5.019410e-03 0.000000e+00 1.092986e+09 0.000000e+00 0.0 0.0 ... 3.346274e-02 0.000000e+00 3.346274e-02 0.0 4.769010e+00 0.000000e+00 4.769010e+00 0.000000e+00 4.769010e+00 1070.0
2 2.399211e+06 1.001819e+07 3.883317e-01 2.200546e+00 3.883317e-01 0.000000e+00 1.437059e+09 0.000000e+00 0.0 0.0 ... 2.588878e+00 0.000000e+00 2.588878e+00 0.0 3.662374e+02 0.000000e+00 3.662374e+02 0.000000e+00 3.662374e+02 1070.0
3 3.636895e+06 1.365505e+07 4.784439e+00 2.711182e+01 4.784439e+00 0.000000e+00 1.965030e+09 0.000000e+00 0.0 0.0 ... 3.189626e+01 0.000000e+00 3.189626e+01 0.0 4.481373e+03 0.000000e+00 4.481373e+03 0.000000e+00 4.481373e+03 1070.0
4 7.372109e+06 2.102697e+07 2.774546e+01 1.572243e+02 2.774546e+01 0.000000e+00 3.051979e+09 0.000000e+00 0.0 0.0 ... 1.849697e+02 0.000000e+00 1.849697e+02 0.0 2.582007e+04 0.000000e+00 2.582007e+04 0.000000e+00 2.582007e+04 1070.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
96 7.591823e+09 3.541404e+11 1.667387e+08 1.552650e+09 4.657949e+09 4.491210e+09 8.508872e+13 1.497070e+09 0.0 0.0 ... 2.223183e+08 4.491210e+09 6.210598e+09 0.0 4.896471e+10 1.297565e+12 4.896471e+10 9.731736e+11 1.346529e+12 1070.0
97 8.003568e+09 3.554404e+11 1.278019e+08 1.675878e+09 5.027633e+09 4.899831e+09 8.530804e+13 1.633277e+09 0.0 0.0 ... 1.704025e+08 4.899831e+09 6.703511e+09 0.0 3.775151e+10 1.415620e+12 3.775151e+10 1.061715e+12 1.453372e+12 1070.0
98 4.560406e+09 3.574687e+11 1.455385e+08 6.330470e+08 1.899141e+09 1.753602e+09 8.552736e+13 5.845342e+08 0.0 0.0 ... 1.940513e+08 1.753602e+09 2.532188e+09 0.0 4.301322e+10 5.066369e+11 4.301322e+10 3.799777e+11 5.496501e+11 1070.0
99 4.619609e+09 3.594903e+11 1.708910e+08 6.494993e+08 1.948498e+09 1.777607e+09 8.574668e+13 5.925356e+08 0.0 0.0 ... 2.278547e+08 1.777607e+09 2.597997e+09 0.0 5.050157e+10 5.135720e+11 5.050157e+10 3.851790e+11 5.640736e+11 1070.0
100 4.700811e+09 3.615007e+11 2.067210e+08 6.725818e+08 2.017745e+09 1.811024e+09 8.596600e+13 6.036748e+08 0.0 0.0 ... 2.756280e+08 1.811024e+09 2.690327e+09 0.0 6.103742e+10 5.232268e+11 6.103742e+10 3.924201e+11 5.842642e+11 1070.0

101 rows × 45 columns

Project grid forward to 100% re in 2050¶

To parallel the PV deployment, we will assume that we globally hit 100% RE in 2050 with the 75 TW of PV. As such, we need to change the future projection of marketshares of the different country grids.

One scenario with decarb grid, one scenario with decarb grid and heat

Estimating that 60-70% generation will be from Solar, 30-40% from wind, and any remainder from "other renewables"

In [8]:
countrygridmix = pd.read_csv(os.path.join(carbonfolder,'baseline_countrygridmix.csv'), index_col='year')
gridsources = ['Bioenergy','Hydro','Nuclear','OtherFossil','OtherRenewables','Solar','Wind']
nonRE = ['Coal','Gas','OtherFossil','Nuclear','Bioenergy']
In [9]:
countrygridmix.loc[2023:,:]=np.nan #delete 2023 to 2050
nonRE_search = '|'.join(nonRE) #create nonRE search
countrygridmix.loc[2050, countrygridmix.columns.str.contains(nonRE_search)] = 0.0 #set all nonRE to 0 in 2050
In [10]:
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Solar')] = 63.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Wind')] = 33.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Hydro')] = 3.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('OtherRenewables')] = 1.0
#numbers derived from leading scenario electricity generation Breyer et al 2022 scenarios (EU focused)
In [11]:
countrygridmix_100RE2050 = countrygridmix.interpolate() #linearly interpolate between 2022 and 2050
In [12]:
apnd_idx = pd.RangeIndex(start=2051,stop=2101,step=1) #create temp df
apnd_df = pd.DataFrame(columns=countrygridmix_100RE2050.columns, index=apnd_idx )
countrygridmix_100RE20502100 = pd.concat([countrygridmix_100RE2050.loc[2000:],apnd_df], axis=0) #extend through 2100
countrygridmix_100RE20502100.ffill(inplace=True) #propogate 2050 values through 2100
In [13]:
countrygridmix_100RE20502100.loc[2050]
Out[13]:
China_Bioenergy            0.0
China_Coal                 0.0
China_Gas                  0.0
China_Hydro                3.0
China_Nuclear              0.0
                          ... 
Zambia_Nuclear             0.0
Zambia_OtherFossil         0.0
Zambia_OtherRenewables     1.0
Zambia_Solar              63.0
Zambia_Wind               33.0
Name: 2050, Length: 472, dtype: float64

This is a simple projection, assumes all countries have same ratio of PV and wind (which we know can't be true). Update in future with country specific projections.

In [14]:
pd.read_csv(os.path.join(carbonfolder,'baseline_electricityemissionfactors.csv'), index_col=[0])
Out[14]:
CO2eq_gpWh_IPCC2006 CO2eq_gpWh_ember CO2_gpWh_EIA CO2_gpWh_EPA
Energy Source
Bioenergy 0.3005 0.230 0.0000 0.3170
Coal 0.3487 0.820 0.3215 0.3380
Gas 0.2291 0.490 0.1805 0.1810
Hydro 0.0000 0.024 0.0000 0.0000
Nuclear 0.0000 0.012 0.0000 0.0000
OtherFossil 0.2671 0.700 0.2413 0.0000
OtherRenewables 0.0000 0.038 0.0000 0.0000
Solar 0.0000 0.048 0.0000 0.0000
Wind 0.0000 0.011 0.0000 0.0000
SteamAndHeat 0.0000 0.000 0.0000 0.2266
In [15]:
sim1.calculateCarbonFlows(countrygridmixes=countrygridmix_100RE20502100)

>>>> Calculating Carbon Flows <<<<

Working on Scenario:  PV_ICE
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  r_PERC
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  r_SHJ
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  r_TOPCon
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  r_IRENA
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  ex_Life
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  ex_High_eff
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  ex_Circular
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  h_EffLife
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  h_50PERC
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  h_RecycledPERC
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  h_Perovskite_life
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
Working on Scenario:  h_Perovskite_Eff
********************
Working on Carbon for Module
==> Working on Carbon for Material :  glass
==> Working on Carbon for Material :  silicon
==> Working on Carbon for Material :  silver
==> Working on Carbon for Material :  aluminium_frames
==> Working on Carbon for Material :  copper
==> Working on Carbon for Material :  encapsulant
==> Working on Carbon for Material :  backsheet
In [ ]:
 

Carbon Analysis¶

this will become the aggregate carbon results function

In [28]:
scenarios = sim1.scenario
In [29]:
#simply group mod and mats carbon dfs by scenario
sim_carbon_dfs = pd.DataFrame()

for scen in scenarios:
    print(scen)
    mod_carbon_scen_results = sim1.scenario[scen].dataOut_c.add_prefix(str(scen+'_'))
    
    scenmatdc = pd.DataFrame()
    for mat in MATERIALS:
        print(mat)
        mat_carbon_scen_results = sim1.scenario[scen].material[mat].matdataOut_c.add_prefix(str(scen+'_'+mat+'_')) 
        scenmatdc = pd.concat([scenmatdc,mat_carbon_scen_results], axis=1) #group all material dc
    
    scen_carbon_results = pd.concat([mod_carbon_scen_results,scenmatdc], axis=1) #append mats to mod
    sim_carbon_dfs = pd.concat([sim_carbon_dfs, scen_carbon_results], axis=1) #append all scens "raw" data

#FIX INDEX of dfs
sim_carbon_dfs.index = pd.RangeIndex(start=2000,stop=2101,step=1)
    
#return sim_carbon_results, sim_annual_carbon
PV_ICE
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
r_PERC
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
r_SHJ
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
r_TOPCon
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
r_IRENA
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
ex_Life
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
ex_High_eff
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
ex_Circular
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
h_EffLife
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
h_50PERC
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
h_RecycledPERC
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
h_Perovskite_life
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
h_Perovskite_Eff
glass
silicon
silver
aluminium_frames
copper
encapsulant
backsheet
In [30]:
#Do math on the carbon dfs, take in the output aggregate sim df
sim_annual_carbon = pd.DataFrame()
for scen in scenarios:
    mod_mfg_carbon_total = sim_carbon_dfs.filter(like=scen).filter(like='Global_mod_MFG') #annual mfging elec carbon
    mod_nonvMFG = ['Install','OandM','Repair','Demount','Store','Resell','ReMFG','Recycle'] #could remove from loop
    nonvMFG_search = '|'.join(mod_nonvMFG) #create nonRE search
    mod_carbon_sum_nonvmfg = sim_carbon_dfs.loc[:,sim_carbon_dfs.columns.str.contains(nonvMFG_search)].filter(like=scen).filter(like='_mod_') #annual non mfging carbon
    scen_annual_carbon_mod = pd.concat([mod_mfg_carbon_total,mod_carbon_sum_nonvmfg], axis=1)
    scen_annual_carbon_mod[scen+'_Annual_Emit_mod_elec_gCO2eq'] = scen_annual_carbon_mod.sum(axis=1)

    scenmatdcmaths = pd.DataFrame()
    for mat in MATERIALS:
        scen_mat_dc_temp = sim_carbon_dfs.filter(like=scen).filter(like=mat)
        #calculation for annual carbon emissions total (selecting to avoid double countings)
        mat_global_vmfg_elec = scen_mat_dc_temp.filter(like='Global_vmfg_elec') #select global mod mfging
        mat_vmfg_countries = scen_mat_dc_temp.filter(like='vmfg_elec') #select country specific mod mfging, includes global
        mat_emit_lifecycle = scen_mat_dc_temp.loc[:,~scen_mat_dc_temp.columns.isin(mat_vmfg_countries.columns)] #select everything not the two above
        
        scen_mat_annual_carbon = pd.concat([mat_global_vmfg_elec,mat_emit_lifecycle], axis=1) #group global mod, lifecycle
        scen_mat_annual_carbon[scen+'_Annual_Emit_'+mat+'_gCO2eq'] = scen_mat_annual_carbon.sum(axis=1) #sum annual emit
        
        scenmatdcmaths = pd.concat([scenmatdcmaths,scen_mat_annual_carbon], axis=1)
        #add by material
        #add by process, fuel, elec
        
        #mat_ce_recycle = mat_carbon_scen_results.filter(like='Recycle_e_p')
        #mat_ce_remfg = mat_carbon_scen_results.filter(like='ReMFG_clean')
        #mat_landfill = mat_carbon_scen_results.filter(like='landfill_total')
        #mat_scen_annual_carbon = pd.concat([mat_vmfg_total,mat_ce_recycle,mat_ce_remfg,mat_landfill], axis=1)
    scen_modmat_annual_carbon = pd.concat([scen_annual_carbon_mod,scenmatdcmaths], axis=1)
    scen_modmat_annual_carbon[scen+'_Annual_Emit_total_modmats_gCO2eq'] = scen_modmat_annual_carbon.filter(like='Annual_Emit').sum(axis=1)
    
    sim_annual_carbon = pd.concat([sim_annual_carbon, scen_modmat_annual_carbon], axis=1)


    #FIX INDEX of dfs
sim_annual_carbon.index = pd.RangeIndex(start=2000,stop=2101,step=1)
In [137]:
#create cumulative
sim_cumu_carbon = sim_annual_carbon.cumsum()
maxy = round(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats_gCO2eq').max()/1e12,-3) #for graphing
sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats_gCO2eq')
Out[137]:
PV_ICE_Annual_Emit_total_modmats_gCO2eq               2.964207e+16
r_PERC_Annual_Emit_total_modmats_gCO2eq               2.210524e+16
r_SHJ_Annual_Emit_total_modmats_gCO2eq                2.104457e+16
r_TOPCon_Annual_Emit_total_modmats_gCO2eq             2.148850e+16
r_IRENA_Annual_Emit_total_modmats_gCO2eq              3.221499e+16
ex_Life_Annual_Emit_total_modmats_gCO2eq              2.274670e+16
ex_High_eff_Annual_Emit_total_modmats_gCO2eq          3.053505e+16
ex_Circular_Annual_Emit_total_modmats_gCO2eq          2.804816e+16
h_EffLife_Annual_Emit_total_modmats_gCO2eq            2.295700e+16
h_50PERC_Annual_Emit_total_modmats_gCO2eq             2.283846e+16
h_RecycledPERC_Annual_Emit_total_modmats_gCO2eq       2.347228e+16
h_Perovskite_life_Annual_Emit_total_modmats_gCO2eq    2.697990e+16
h_Perovskite_Eff_Annual_Emit_total_modmats_gCO2eq     2.349308e+16
Name: 2100, dtype: float64
In [ ]:
 

Carbon Emissions Cumulative Scenario compare¶

In [141]:
sim_cumu_carbon_mmt = sim_cumu_carbon.filter(like='Annual_Emit_total_modmats_gCO2eq')/1e12
sim_cumu_carbon_mmt
Out[141]:
PV_ICE_Annual_Emit_total_modmats_gCO2eq r_PERC_Annual_Emit_total_modmats_gCO2eq r_SHJ_Annual_Emit_total_modmats_gCO2eq r_TOPCon_Annual_Emit_total_modmats_gCO2eq r_IRENA_Annual_Emit_total_modmats_gCO2eq ex_Life_Annual_Emit_total_modmats_gCO2eq ex_High_eff_Annual_Emit_total_modmats_gCO2eq ex_Circular_Annual_Emit_total_modmats_gCO2eq h_EffLife_Annual_Emit_total_modmats_gCO2eq h_50PERC_Annual_Emit_total_modmats_gCO2eq h_RecycledPERC_Annual_Emit_total_modmats_gCO2eq h_Perovskite_life_Annual_Emit_total_modmats_gCO2eq h_Perovskite_Eff_Annual_Emit_total_modmats_gCO2eq
2000 1.436637 1.248665 1.199394 1.223802 1.436637 1.339473 1.194566 1.436637 1.194566 1.339473 1.462665 1.436637 1.436637
2001 1.909237 1.775803 1.740827 1.758153 1.909237 1.840264 1.737400 1.909237 1.737400 1.840264 1.944515 1.909237 1.909237
2002 2.413579 2.247151 2.203526 2.225136 2.413579 2.327551 2.199252 2.413579 2.199252 2.327551 2.460202 2.413579 2.413579
2003 3.097123 2.885977 2.830631 2.858048 3.097121 2.987980 2.825208 3.097123 2.825208 2.987980 3.161400 3.097123 3.097123
2004 4.328861 4.037132 3.960664 3.998544 4.328843 4.178064 3.953171 4.328861 3.953171 4.178064 4.428316 4.328861 4.328861
... ... ... ... ... ... ... ... ... ... ... ... ... ...
2096 28440.242934 21552.285719 20518.555813 20951.276320 30544.274814 20750.854245 28271.738204 27154.070900 22397.551464 21400.300884 22542.646919 26307.102565 22731.510374
2097 28713.313526 21735.274796 20692.626559 21129.057883 30961.711458 21224.619726 28813.300118 27378.725357 22531.730102 21753.030840 22765.126159 26466.257999 22921.105303
2098 29003.781584 21857.338175 20808.742681 21247.649219 31380.505264 21716.414143 29373.501078 27602.699149 22668.934486 22111.322011 22992.241094 26626.408303 23111.228856
2099 29311.889152 21980.530888 20925.933074 21367.337730 31797.587613 22224.607777 29947.906169 27825.867869 22810.230956 22473.740092 23228.291931 26787.725830 23301.886569
2100 29642.071628 22105.244013 21044.569746 21488.503353 32214.986299 22746.698479 30535.051871 28048.159358 22957.003214 22838.456854 23472.280720 26979.902562 23493.079852

101 rows × 13 columns

In [146]:
fig_cumu_carbon, (ax1,ax2,ax3) = plt.subplots(1,3,figsize=(15,5), sharey=True, sharex=True, 
                                      gridspec_kw={'wspace':0})

#BAU
ax1.set_prop_cycle(color=colorpalette[0:5])
ax1.plot(sim_cumu_carbon_mmt.iloc[:,0:5], label=scennames_labels_flat[0:5]) # baselines
ax1.set_title('Business as Usual', fontsize=14)
ax1.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes CO2 eq]', fontsize=20)
ax1.set_xlim(2000,2100)
ax1.legend(bbox_to_anchor=(0.9,-0.05))
ax1.set_ylim(0,maxy+1000)
ax1.xaxis.set_minor_locator(MultipleLocator(10))
ax1.grid(axis='both', which='both', color='0.9', ls='--') 


#Extreme
ax2.set_prop_cycle(color=colorpalette[5:8])

ax2.plot(sim_cumu_carbon_mmt.iloc[:,5:8], label=scennames_labels_flat[5:8])
ax2.xaxis.set_minor_locator(MultipleLocator(10))
ax2.grid(axis='both', which='both', color='0.9', ls='--') 

#create glowlines for Extreme scens
n_lines = 10
diff_linewidth = 1.05
alpha_value = 0.05
for n in range(1, n_lines+1):    
    ax2.plot(sim_cumu_carbon_mmt.iloc[:,5],
            linewidth=2+(diff_linewidth*n),
            alpha=alpha_value,
            color=colorpalette[5])

for n in range(1, n_lines+1):    
    ax2.plot(sim_cumu_carbon_mmt.iloc[:,6],
            linewidth=2+(diff_linewidth*n),
            alpha=alpha_value,
            color=colorpalette[6])

for n in range(1, n_lines+1):    
    ax2.plot(sim_cumu_carbon_mmt.iloc[:,7],
            linewidth=2+(diff_linewidth*n),
            alpha=alpha_value,
            color=colorpalette[7])

ax2.set_title('Extreme', fontsize=14)
ax2.legend(bbox_to_anchor=(0.9,-0.05))

#Ambitious
ax3.set_prop_cycle(color=colorpalette[8:])
ax3.plot(sim_cumu_carbon_mmt.iloc[:,8:], label=scennames_labels_flat[8:], ls='--')# 
ax3.set_title('Ambitious', fontsize=14)
ax3.legend(bbox_to_anchor=(1.05,-0.05)) #(x,y)
ax3.xaxis.set_minor_locator(MultipleLocator(10))
ax3.grid(axis='both', which='both', color='0.9', ls='--') 

#overall figure

fig_cumu_carbon.suptitle('Cumulative Carbon Emissions', fontsize=24, y=1)
plt.show()
#fig_cumu_carbon.savefig('energyresults-annualMatDemands-decade.png', dpi=300, bbox_inches='tight')

Cabon Emissions by material or module¶

In [31]:
for scen in scenarios:

    scen_annual_carbon = sim_annual_carbon.filter(like='Annual_Emit').filter(like=scen)/1e12 #million tonnes
    
    plt.plot([],[],color=colormats[0], label=MATERIALS[0])
    plt.plot([],[],color=colormats[1], label=MATERIALS[1])
    plt.plot([],[],color=colormats[2], label=MATERIALS[2])
    plt.plot([],[],color=colormats[3], label=MATERIALS[3])
    plt.plot([],[],color=colormats[4], label=MATERIALS[4])
    plt.plot([],[],color=colormats[5], label=MATERIALS[5])
    plt.plot([],[],color=colormats[6], label=MATERIALS[6])
    plt.plot([],[],color=colormats[7], label='module')


    plt.stackplot(scen_annual_carbon.index,
                  scen_annual_carbon[scen+'_Annual_Emit_glass_gCO2eq'], 
                  scen_annual_carbon[scen+'_Annual_Emit_silicon_gCO2eq'],
                  scen_annual_carbon[scen+'_Annual_Emit_silver_gCO2eq'], 
                  scen_annual_carbon[scen+'_Annual_Emit_aluminium_frames_gCO2eq'], 
                  scen_annual_carbon[scen+'_Annual_Emit_copper_gCO2eq'],
                  scen_annual_carbon[scen+'_Annual_Emit_encapsulant_gCO2eq'],
                  scen_annual_carbon[scen+'_Annual_Emit_backsheet_gCO2eq'],
                  scen_annual_carbon[scen+'_Annual_Emit_mod_elec_gCO2eq'],
                  colors = colormats)
    plt.title(scen+':\nGHG Emissions Annually by Module and Material Lifecycle')
    plt.ylabel('GHG Emissions Annually from Lifecycle Mats and Mods\n[million metric tonnes CO2eq]')
    plt.xlim(2000,2100)

    handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
    plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.45,1))

#plt.legend()
    plt.show()
In [37]:

Out[37]:
PV_ICE_Annual_Emit_total_modmats_gCO2eq               2.964207e+16
r_PERC_Annual_Emit_total_modmats_gCO2eq               2.210524e+16
r_SHJ_Annual_Emit_total_modmats_gCO2eq                2.104457e+16
r_TOPCon_Annual_Emit_total_modmats_gCO2eq             2.148850e+16
r_IRENA_Annual_Emit_total_modmats_gCO2eq              3.221499e+16
ex_Life_Annual_Emit_total_modmats_gCO2eq              2.274670e+16
ex_High_eff_Annual_Emit_total_modmats_gCO2eq          3.053505e+16
ex_Circular_Annual_Emit_total_modmats_gCO2eq          2.804816e+16
h_EffLife_Annual_Emit_total_modmats_gCO2eq            2.295700e+16
h_50PERC_Annual_Emit_total_modmats_gCO2eq             2.283846e+16
h_RecycledPERC_Annual_Emit_total_modmats_gCO2eq       2.347228e+16
h_Perovskite_life_Annual_Emit_total_modmats_gCO2eq    2.697990e+16
h_Perovskite_Eff_Annual_Emit_total_modmats_gCO2eq     2.349308e+16
Name: 2100, dtype: float64
In [38]:
maxy
Out[38]:
32000.0
In [136]:
#colormats = ['#00bfbf','#ff7f0e','#1f77be','#2ca02c','#d62728','#9467BD','#8C564B','black'] #colors for material plots
for scen in scenarios:

    scen_cumu_carbon = sim_cumu_carbon.filter(like='Annual_Emit').filter(like=scen)/1e12 #million tonnes
    
    plt.plot([],[],color=colormats[0], label=MATERIALS[0])
    plt.plot([],[],color=colormats[1], label=MATERIALS[1])
    plt.plot([],[],color=colormats[2], label=MATERIALS[2])
    plt.plot([],[],color=colormats[3], label=MATERIALS[3])
    plt.plot([],[],color=colormats[4], label=MATERIALS[4])
    plt.plot([],[],color=colormats[5], label=MATERIALS[5])
    plt.plot([],[],color=colormats[6], label=MATERIALS[6])
    plt.plot([],[],color=colormats[7], label='module')


    plt.stackplot(scen_cumu_carbon.index,
                  scen_cumu_carbon[scen+'_Annual_Emit_glass_gCO2eq'], 
                  scen_cumu_carbon[scen+'_Annual_Emit_silicon_gCO2eq'],
                  scen_cumu_carbon[scen+'_Annual_Emit_silver_gCO2eq'], 
                  scen_cumu_carbon[scen+'_Annual_Emit_aluminium_frames_gCO2eq'], 
                  scen_cumu_carbon[scen+'_Annual_Emit_copper_gCO2eq'],
                  scen_cumu_carbon[scen+'_Annual_Emit_encapsulant_gCO2eq'],
                  scen_cumu_carbon[scen+'_Annual_Emit_backsheet_gCO2eq'],
                  scen_cumu_carbon[scen+'_Annual_Emit_mod_elec_gCO2eq'],
                  colors = colormats)
    plt.title(scen+':\nGHG Emissions Annually by Module and Material Lifecycle')
    plt.ylabel('GHG Emissions Annually from Lifecycle Mats and Mods\n[million metric tonnes CO2eq]')
    plt.xlim(2000,2100)
    plt.ylim(0,maxy+1000)

    handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
    plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.45,1))
    plt.grid(axis='both', which='both', color='0.9', ls='--')
#plt.legend()
    plt.show()
In [46]:
sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_mod_elec')
Out[46]:
PV_ICE_Annual_Emit_mod_elec_gCO2eq               8.661511e+13
r_PERC_Annual_Emit_mod_elec_gCO2eq               7.955485e+13
r_SHJ_Annual_Emit_mod_elec_gCO2eq                7.575890e+13
r_TOPCon_Annual_Emit_mod_elec_gCO2eq             7.733545e+13
r_IRENA_Annual_Emit_mod_elec_gCO2eq              1.014963e+14
ex_Life_Annual_Emit_mod_elec_gCO2eq              8.112453e+13
ex_High_eff_Annual_Emit_mod_elec_gCO2eq          6.481039e+13
ex_Circular_Annual_Emit_mod_elec_gCO2eq          1.238429e+14
h_EffLife_Annual_Emit_mod_elec_gCO2eq            6.864642e+13
h_50PERC_Annual_Emit_mod_elec_gCO2eq             8.163300e+13
h_RecycledPERC_Annual_Emit_mod_elec_gCO2eq       3.024845e+14
h_Perovskite_life_Annual_Emit_mod_elec_gCO2eq    1.173374e+14
h_Perovskite_Eff_Annual_Emit_mod_elec_gCO2eq     1.055897e+14
Name: 2100, dtype: float64
In [47]:
#create a df from which to do a bar chart of 2100 emissions by mat/mod
mats_emit_2100 = pd.DataFrame() #index=scennames_labels_flat
for mat in MATERIALS:
    mat_emit_2100 = pd.Series(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_'+mat).values)
    mats_emit_2100 = pd.concat([mats_emit_2100, mat_emit_2100], axis=1)

mats_emit_2100
mats_emit_2100.columns = MATERIALS
modmats_emit_2100 = pd.concat([mats_emit_2100,pd.Series(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_mod_elec').values)], axis=1)
modmats_emit_2100.index = scennames_labels_flat
modmats_emit_2100.rename(columns={0:'module'}, inplace=True)
modmats_emit_2100_megatonne = modmats_emit_2100/1e12
modmats_emit_2100_megatonne
Out[47]:
glass silicon silver aluminium_frames copper encapsulant backsheet module
PV_ICE 10128.661994 6393.528822 39.555545 7759.907146 8.553999 3013.443849 2211.805161 86.615111
PERC 9100.755660 5083.297261 25.191311 4986.668409 7.933845 2800.113453 21.729228 79.554845
SHJ 8652.812210 4837.013804 44.794737 4742.685932 7.545504 2662.628153 21.330504 75.758903
TOPCon 8837.278528 4938.802814 43.333633 4843.242140 7.705695 2719.277076 21.528020 77.335447
Low Quality 11526.374030 5202.740656 40.635431 7133.665114 12.970040 4731.060652 3466.044108 101.496270
Long-Lived 9270.300576 5078.154692 29.471217 6013.562121 6.784228 2244.838020 22.463092 81.124534
High Eff 12963.265329 6145.955317 38.732726 8176.784091 8.755677 3115.456836 21.291503 64.810392
Circular 8996.350286 4412.185490 92.251404 6254.983351 21.597082 8123.698405 23.250434 123.842906
High Eff + Long-life 9507.952013 4926.966042 31.290604 6098.983567 6.741955 2295.131175 21.291435 68.646424
Long-Life + Recycling 9444.863234 5171.277979 32.719877 5717.789805 6.882528 2360.827092 22.463337 81.633002
Recycled-Si + Long-life 8876.675002 2259.159910 33.593199 4978.766570 11.277104 4044.829561 2965.494878 302.484496
Circular + Long-life 8839.142638 6474.457856 66.818549 5916.944139 15.130176 5526.821345 23.250434 117.337425
Circular + High Eff 6880.106946 5865.683841 68.893415 4657.933648 15.835931 5875.785931 23.250434 105.589706
In [51]:
fig_cumuemit_modmat, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True, 
                                      gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['glass'], color=colormats[0])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['silicon'],
        bottom=modmats_emit_2100_megatonne[0:5]['glass'], color=colormats[1])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['silver'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:2].sum(axis=1), color=colormats[2])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['aluminium_frames'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:3].sum(axis=1), color=colormats[3])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['copper'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:4].sum(axis=1), color=colormats[4])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['encapsulant'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:5].sum(axis=1), color=colormats[5])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['backsheet'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:6].sum(axis=1), color=colormats[6])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['module'],
       bottom=modmats_emit_2100_megatonne.iloc[0:5,0:7].sum(axis=1), color='black')

ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes CO2eq]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--') 
ax0.set_axisbelow(True)

#Extreme
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['glass'], color=colormats[0])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['silicon'],
        bottom=modmats_emit_2100_megatonne[5:8]['glass'], color=colormats[1])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['silver'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:2].sum(axis=1), color=colormats[2])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['aluminium_frames'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:3].sum(axis=1), color=colormats[3])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['copper'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:4].sum(axis=1), color=colormats[4])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['encapsulant'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:5].sum(axis=1), color=colormats[5])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['backsheet'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:6].sum(axis=1), color=colormats[6])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['module'],
       bottom=modmats_emit_2100_megatonne.iloc[5:8,0:7].sum(axis=1), color='black')

ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--') 
ax2.set_axisbelow(True)

#Ambitious
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['glass'], color=colormats[0])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['silicon'],
        bottom=modmats_emit_2100_megatonne[8:]['glass'], color=colormats[1])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['silver'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:2].sum(axis=1), color=colormats[2])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['aluminium_frames'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:3].sum(axis=1), color=colormats[3])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['copper'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:4].sum(axis=1), color=colormats[4])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['encapsulant'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:5].sum(axis=1), color=colormats[5])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['backsheet'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:6].sum(axis=1), color=colormats[6])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['module'],
       bottom=modmats_emit_2100_megatonne.iloc[8:,0:7].sum(axis=1), color='black')


ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--') 
ax3.set_axisbelow(True)

#overall fig

fig_cumuemit_modmat.suptitle('Cumulative Emisisons in 2100 by material', fontsize=24)
plt.show()

#fig_cumuemit_modmat.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_18080\1654097834.py:23: UserWarning: FixedFormatter should only be used together with FixedLocator
  ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_18080\1654097834.py:45: UserWarning: FixedFormatter should only be used together with FixedLocator
  ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_18080\1654097834.py:68: UserWarning: FixedFormatter should only be used together with FixedLocator
  ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)

Cumulative Carbon in 2050 and 2100¶

In [52]:
#mins in 2050 and 2100
cumu_carbon_2050 = sim_cumu_carbon.loc[2050].filter(like='Annual_Emit_total_modmats')/1e12
cumu_carbon_2100 = sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats')/1e12
cumu_carbon_rankings_crittime = pd.concat([cumu_carbon_2050,cumu_carbon_2100], axis=1)
cumu_carbon_rankings_crittime.index = scennames_labels_flat
cumu_carbon_rankings_crittime
Out[52]:
2050 2100
PV_ICE 14059.020878 29642.071628
PERC 12800.290860 22105.244013
SHJ 12193.770105 21044.569746
TOPCon 12448.897638 21488.503353
Low Quality 15169.837923 32214.986299
Long-Lived 13425.139177 22746.698479
High Eff 10927.903642 30535.051871
Circular 17620.780689 28048.159358
High Eff + Long-life 11214.153901 22957.003214
Long-Life + Recycling 13441.057091 22838.456854
Recycled-Si + Long-life 14299.423757 23472.280720
Circular + Long-life 18319.502170 26979.902562
Circular + High Eff 15083.986429 23493.079852
In [53]:
cumu_carbon_rankings_crittime_plot = cumu_carbon_rankings_crittime.copy()
cumu_carbon_rankings_crittime_plot['diff'] = cumu_carbon_rankings_crittime[2100]-cumu_carbon_rankings_crittime[2050]
In [56]:
fig_cumulativeemit, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True, 
                                      gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(cumu_carbon_rankings_crittime_plot.index[0:5], cumu_carbon_rankings_crittime_plot[2050].iloc[0:5],
        tick_label=scennames_labels[0:5], color=colorpalette[0:5], alpha = 0.7, edgecolor='white')
ax0.bar(cumu_carbon_rankings_crittime_plot.index[0:5], cumu_carbon_rankings_crittime_plot['diff'].iloc[0:5],
        bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[0:5],
        tick_label=scennames_labels[0:5], color=colorpalette[0:5])
ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes CO2eq]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--') 
ax0.set_axisbelow(True)

#Extreme
ax2.bar(cumu_carbon_rankings_crittime_plot.index[5:8], cumu_carbon_rankings_crittime_plot[2050].iloc[5:8],
        tick_label=scennames_labels[5:8], color=colorpalette[5:8], alpha = 0.7, edgecolor='white')
ax2.bar(cumu_carbon_rankings_crittime_plot.index[5:8], cumu_carbon_rankings_crittime_plot['diff'].iloc[5:8],
        bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[5:8],
        tick_label=scennames_labels[5:8], color=colorpalette[5:8])
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--') 
ax2.set_axisbelow(True)

#Ambitious
ax3.bar(cumu_carbon_rankings_crittime_plot.index[8:], cumu_carbon_rankings_crittime_plot[2050].iloc[8:],
        tick_label=scennames_labels[8:], color=colorpalette[8:], hatch='x', edgecolor='white', alpha=0.7)
ax3.bar(cumu_carbon_rankings_crittime_plot.index[8:], cumu_carbon_rankings_crittime_plot['diff'].iloc[8:],
        bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[8:],
        tick_label=scennames_labels[8:], color=colorpalette[8:], hatch='x', edgecolor='white')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--') 
ax3.set_axisbelow(True)

#overall fig

fig_cumulativeemit.suptitle('Cumulative Emisisons in 2050, 2100', fontsize=24)
plt.show()

#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')

¶

Emissions by electricity vs fuels vs process¶

Process emission summing¶

This only happens on the material files

In [57]:
process_emissions = pd.DataFrame()
for scen in scenarios:
    scen_p = sim_carbon_dfs.filter(like=scen).filter(like='_p_')
    scen_p_sum = scen_p.sum(axis=1)
    process_emissions = pd.concat([process_emissions,scen_p_sum], axis=1)

process_emissions.columns = scennames_labels_flat
process_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
process_emissions_cumu = process_emissions.cumsum()
In [67]:
#process_emissions_cumu

Fuel Emissions¶

This is capturing steam and heating fuel, also only on material level

In [68]:
fuel_emissions = pd.DataFrame()
for scen in scenarios:
    scen_f = sim_carbon_dfs.filter(like=scen).filter(like='_fuel_')
    scen_f_sum = scen_f.sum(axis=1)
    fuel_emissions = pd.concat([fuel_emissions,scen_f_sum], axis=1)
    
fuel_emissions.columns = scennames_labels_flat
fuel_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
fuel_emissions_cumu = fuel_emissions.cumsum()
In [74]:
#fuel_emissions_cumu

Electricity Emissions¶

both module and material level elec.

In [88]:
elec_emissions = pd.DataFrame()
for scen in scenarios:
    scen_mod_elec = sim_carbon_dfs.filter(like=scen).filter(like='Global_mod_MFG') #module elec lifecycle emits
    
    #material elec emits
    mat_eleckey = ['Global_vmfg_elec','landfill_elec','ReMFG_clean_elec','Recycled_LQ_elec','Recycled_HQ_elec']
    mat_elecs_search = '|'.join(mat_eleckey)
    scen_mat_elecs = sim_carbon_dfs.loc[:,sim_carbon_dfs.columns.str.contains(mat_elecs_search)].filter(like=scen)
    scen_mat_elecs_sum = scen_mat_elecs.sum(axis=1)
    
    #sum them together by scen
    scen_elec_modmat_annual_sum = scen_mat_elecs_sum+scen_mod_elec.iloc[:,0]
    elec_emissions = pd.concat([elec_emissions,scen_elec_modmat_annual_sum], axis=1)
    
elec_emissions.columns=scennames_labels_flat
elec_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
elec_emissions_cumu = elec_emissions.cumsum()
In [97]:
#graphing by emission source
efp_emit_total = elec_emissions+fuel_emissions+process_emissions
efp_emit_total_cumu = elec_emissions_cumu+fuel_emissions_cumu+process_emissions_cumu
In [130]:
#graphing by emission source, annual
#efp_emit_total = elec_emissions+fuel_emissions+process_emissions

for scen in scennames_labels_flat:
    
    plt.plot([],[],color='black', label='process')
    plt.plot([],[],color='darkred', label='fuel')
    plt.plot([],[],color='blue', label='electricity')

    plt.stackplot(elec_emissions.index,
                  process_emissions[scen]/1e12, 
                  fuel_emissions[scen]/1e12,
                  elec_emissions[scen]/1e12, 
                  colors = ['black','darkred','blue'])
    plt.title(scen+':\nGHG Emissions Annually by Source')
    plt.ylabel('GHG Emissions Annually from Lifecycle Source\n[million metric tonnes CO2eq]')
    plt.xlim(2000,2100)
    plt.ylim(0,)

    handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
    plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.4,1))
    #plt.grid(axis='both', which='both', color='0.9', ls='--', zorder=0)
    #plt.set_axisbelow(True)
#plt.legend()
    plt.show()
In [135]:
#graphing by emission source, cumulative

for scen in scennames_labels_flat:
    
    plt.plot([],[],color='black', label='process')
    plt.plot([],[],color='darkred', label='fuel')
    plt.plot([],[],color='blue', label='electricity')

    plt.stackplot(elec_emissions_cumu.index,
                  process_emissions_cumu[scen]/1e12, 
                  fuel_emissions_cumu[scen]/1e12,
                  elec_emissions_cumu[scen]/1e12, 
                  colors = ['black','darkred','blue'])
    plt.title(scen+':\nGHG Emissions Cumulative by Source')
    plt.ylabel('GHG Emissions Cumulatively from Lifecycle Source\n[million metric tonnes CO2eq]')
    plt.xlim(2000,2100)
    plt.ylim(0,maxy+1000)

    handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
    plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.3,1))
    plt.grid(axis='both', which='both', color='0.9', ls='--')
#plt.legend()
    plt.show()
In [109]:
#bar chart 2050 and 2100 by scenario by emission source
emit_efp_2100_forbar = pd.concat([elec_emissions_cumu.loc[2100],fuel_emissions_cumu.loc[2100],process_emissions_cumu.loc[2100]],
                                 axis=1,keys=['electricity','fuel','process'])
In [113]:
emit_efp_2100_mmt = emit_efp_2100_forbar/1e12
In [162]:
fig_cumulativeemit, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True, 
                                      gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['process'].iloc[0:5],label='process',
        tick_label=scennames_labels[0:5], color='black')

ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['fuel'].iloc[0:5],label='fuel',
        bottom=emit_efp_2100_mmt['process'].iloc[0:5], 
        tick_label=scennames_labels[0:5], color='darkred')

ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['electricity'].iloc[0:5],label='electricity',
        bottom=emit_efp_2100_mmt['process'].iloc[0:5]+emit_efp_2100_mmt['fuel'].iloc[0:5],
        tick_label=scennames_labels[0:5], color='blue')

ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes CO2eq]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--') 
ax0.set_axisbelow(True)

#Extreme
ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['process'].iloc[5:8],
        tick_label=scennames_labels[5:8], color='black')

ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['fuel'].iloc[5:8],
        bottom=emit_efp_2100_mmt['process'].iloc[5:8], 
        tick_label=scennames_labels[5:8], color='darkred')

ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['electricity'].iloc[5:8],
        bottom=emit_efp_2100_mmt['process'].iloc[5:8]+emit_efp_2100_mmt['fuel'].iloc[5:8],
        tick_label=scennames_labels[5:8], color='blue')

ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--') 
ax2.set_axisbelow(True)

#Ambitious
ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['process'].iloc[8:],
        tick_label=scennames_labels[8:], color='black')

ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['fuel'].iloc[8:],
        bottom=emit_efp_2100_mmt['process'].iloc[8:], 
        tick_label=scennames_labels[8:], color='darkred')

ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['electricity'].iloc[8:],
        bottom=emit_efp_2100_mmt['process'].iloc[8:]+emit_efp_2100_mmt['fuel'].iloc[8:],
        tick_label=scennames_labels[8:], color='blue')

ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--') 
ax3.set_axisbelow(True)

#overall fig
fig_cumulativeemit.suptitle('Cumulative Emisisons in 2100 by emission source', fontsize=24)
handles, labels = plt.gca().get_legend_handles_labels()
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.42,1))
plt.show()

#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
In [ ]:
 

vMFG versus Circular Processes¶

3 categories for this:

  • vmfg of materials
  • CE of materials and materials
  • install/decomission requirements and I think module mfging falls into the last category
In [180]:
CEkey = ['ReMFG','Recycled','Resell','Repair','LQ','HQ']
CEkey_search = '|'.join(CEkey)

LinearKey = ['vMFG', 'landfill']
LinearKey_search = '|'.join(LinearKey)

otherkey = ['mod_MFG','OandM','Install','Demount', 'Store'] #THIS ONE IS MISSING COLUMNS!!!
otherkey_search = '|'.join(otherkey)
In [186]:
#subset by pathways
sim_carbon_CE = pd.DataFrame()
sim_carbon_linear = pd.DataFrame()
sim_carbon_necessary = pd.DataFrame()

for scen in scenarios:
    scen_annual_carbon = sim_annual_carbon.filter(like=scen)
    
    scen_carbon_CE = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(CEkey_search)]
    scen_carbon_CE_sum = scen_carbon_CE.sum(axis=1)
    sim_carbon_CE = pd.concat([sim_carbon_CE, scen_carbon_CE_sum], axis=1)
    
    scen_carbon_linear = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(LinearKey_search)]
    scen_carbon_linear_sum = scen_carbon_linear.sum(axis=1)
    sim_carbon_linear = pd.concat([sim_carbon_linear,scen_carbon_linear_sum ], axis=1)
    
    scen_carbon_other = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(otherkey_search)]
    scen_carbon_other_sum = scen_carbon_other.sum(axis=1)
    sim_carbon_necessary = pd.concat([sim_carbon_necessary, scen_carbon_other_sum], axis=1)
    
sim_carbon_CE.columns = scennames_labels_flat
sim_carbon_linear.columns = scennames_labels_flat
sim_carbon_necessary.columns = scennames_labels_flat

#.index = pd.RangeIndex(start=2000,stop=2101,step=1)
In [189]:
sim_carbon_CE_cumu = sim_carbon_CE.cumsum()
sim_carbon_linear_cumu = sim_carbon_linear.cumsum()
sim_carbon_necessary_cumu = sim_carbon_necessary.cumsum()
In [190]:
emit_pathway = pd.concat([sim_carbon_CE_cumu.loc[2100],sim_carbon_linear_cumu.loc[2100],sim_carbon_necessary_cumu.loc[2100]],
                                 axis=1,keys=['Circular','Linear/Virgin','Necessary'])
emit_pathway_mmt = emit_pathway/1e12
In [197]:
emit_pathway.sum(axis=1) #I am not catching all emissions =/
Out[197]:
PV_ICE                     1.665571e+16
PERC                       1.235716e+16
SHJ                        1.175186e+16
TOPCon                     1.200171e+16
Low Quality                2.110478e+16
Long-Lived                 1.198417e+16
High Eff                   1.677574e+16
Circular                   1.793733e+16
High Eff + Long-life       1.229974e+16
Long-Life + Recycling      1.207110e+16
Recycled-Si + Long-life    8.443357e+16
Circular + Long-life       1.545179e+16
Circular + High Eff        1.387950e+16
dtype: float64
In [195]:
fig_emitByPathway, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True, 
                                      gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Necessary'].iloc[0:5],label='Necessary',
        tick_label=scennames_labels[0:5], color='darkgray')

ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Linear/Virgin'].iloc[0:5],label='Linear/Virgin',
        bottom=emit_pathway_mmt['Necessary'].iloc[0:5], 
        tick_label=scennames_labels[0:5], color='darkorange')

ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Circular'].iloc[0:5],label='Circular',
        bottom=emit_pathway_mmt['Necessary'].iloc[0:5]+emit_pathway_mmt['Linear/Virgin'].iloc[0:5],
        tick_label=scennames_labels[0:5], color='green')

ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes CO2eq]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--') 
ax0.set_axisbelow(True)

#Extreme
ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['process'].iloc[5:8],
        tick_label=scennames_labels[5:8], color='black')

ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['fuel'].iloc[5:8],
        bottom=emit_efp_2100_mmt['process'].iloc[5:8], 
        tick_label=scennames_labels[5:8], color='darkred')

ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['electricity'].iloc[5:8],
        bottom=emit_efp_2100_mmt['process'].iloc[5:8]+emit_efp_2100_mmt['fuel'].iloc[5:8],
        tick_label=scennames_labels[5:8], color='blue')

ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--') 
ax2.set_axisbelow(True)

#Ambitious
ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['process'].iloc[8:],
        tick_label=scennames_labels[8:], color='black')

ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['fuel'].iloc[8:],
        bottom=emit_efp_2100_mmt['process'].iloc[8:], 
        tick_label=scennames_labels[8:], color='darkred')

ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['electricity'].iloc[8:],
        bottom=emit_efp_2100_mmt['process'].iloc[8:]+emit_efp_2100_mmt['fuel'].iloc[8:],
        tick_label=scennames_labels[8:], color='blue')

ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--') 
ax3.set_axisbelow(True)

#overall fig
fig_emitByPathway.suptitle('Cumulative Emisisons in 2100 by emission source', fontsize=24)
handles, labels = plt.gca().get_legend_handles_labels()
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.42,1))
plt.show()

#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
In [ ]: